﻿#include "StdAfx.h"
#include "Globals.h"
#include "Model.h"
#include "Marco.h"
#include <string>
using namespace std;

#define MAX_LENGTH 100000

using namespace std;

Model::Model() : m_Rotate(Vector3(0, 0, 0)), m_Position(Vector3(0, 0, 0)), m_Scale(Vector3(1, 1, 1))
{

}

Matrix Model::getWorld()
{
	Matrix ma_Trans, ma_Scale, ma_Rotate, ma_RX, ma_RY, ma_RZ;
	ma_Trans.SetTranslation(m_Position.x, m_Position.y, m_Position.z);
	ma_Scale.SetScale(m_Scale.x, m_Scale.y, m_Scale.z);
	ma_Rotate.SetIdentity();
	ma_RX.SetRotationX(m_Rotate.x);
	ma_RY.SetRotationY(m_Rotate.y);
	ma_RZ.SetRotationZ(m_Rotate.z);
	ma_Rotate = ma_RZ * ma_RX * ma_RY;
	return ma_Scale * ma_Rotate * ma_Trans;
}

Matrix Model::getInvertWorld()
{
	Matrix ma_Trans, ma_Scale, ma_Rotate, ma_RX, ma_RY, ma_RZ;

	//Invert Translate Matrix
	ma_Trans.SetTranslation(-m_Position);

	//invert Scale Matrix
	ma_Scale.SetScale(1.0f / m_Scale.x, 1.0f / m_Scale.y, 1.0f / m_Scale.z);

	ma_Rotate.SetIdentity();
	ma_RX.SetRotationX(-m_Rotate.x);
	ma_RY.SetRotationY(-m_Rotate.y);
	ma_RZ.SetRotationZ(-m_Rotate.z);
	ma_Rotate = ma_RY * ma_RX * ma_RZ;
	//Invert Rotation Matrix
	return ma_Trans*ma_Rotate*ma_Scale;
}

void Model::draw(Shaders* sha)
{
	Matrix MVP, World;
	World = getWorld();
	MVP.SetIdentity();
	MVP = World * Globals::currentCamera->ViewMatrix() * Globals::currentCamera->projection;
	if (sha->u_MatrixMVP != -1)	// Send MVP
		glUniformMatrix4fv(sha->u_MatrixMVP, 1, GL_FALSE, (float*)&MVP);

	if (sha->u_World != -1)	// Send World
		glUniformMatrix4fv(sha->u_World, 1, GL_FALSE, (float*)&World);

	if (sha->u_Camera != -1)	// Send Camera
		glUniform3fv(sha->u_Camera, 1, (float*)&Globals::currentCamera->GetPosition());

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	int size;
	glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
	size /= sizeof(Vertex);
	if (sha->a_positon != -1)
	{
		glEnableVertexAttribArray(sha->a_positon);
		glVertexAttribPointer(sha->a_positon, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	}

	if (sha->a_uv != -1)
	{
		glEnableVertexAttribArray(sha->a_uv);
		glVertexAttribPointer(sha->a_uv, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
	}

	if (sha->a_normal != -1)
	{
		glEnableVertexAttribArray(sha->a_normal);
		glVertexAttribPointer(sha->a_normal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);
	}

	if (sha->a_tangent != -1)
	{
		glEnableVertexAttribArray(sha->a_tangent);
		glVertexAttribPointer(sha->a_tangent, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)32);
	}

	if (sha->a_binormal != -1)
	{
		glEnableVertexAttribArray(sha->a_binormal);
		glVertexAttribPointer(sha->a_binormal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)44);
	}

}

void Model::SetVertices(Vertex* vertices, int iCount)
{
	m_NumVertices = iCount;

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)* m_NumVertices, vertices, GL_STATIC_DRAW);
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	
}

	
void Model::SetIndices(unsigned short* indices, int iCount)
{
	m_NumIndices = iCount;
	glGenBuffers(1, &IND);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)* m_NumIndices, indices, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

Model::Model(Vertex* vd, int numVer, unsigned short* id, int numInd) : m_Rotate(Vector3(0, 0, 0)), m_Position(Vector3(0, 0, 0)), m_Scale(Vector3(1, 1, 1))
{
	SetVertices(vd, numVer);
	SetIndices(id, numInd);
	Delete_Array(vd);
	Delete_Array(id);
}

Model::~Model(void) 
{
	glDeleteBuffers(1,&this->VBO);
	glDeleteBuffers(1,&this->IND);
}

// Set Properties
void Model::setTextureID(GLuint id)
{
	m_IdTexture = id;
}

// Get Properties
GLuint Model::getTextureID()
{
	return m_IdTexture;
}

int Model::getNumIndices()
{
	return m_NumIndices;
}

int Model::getNumVertices()
{
	return m_NumVertices;
}

